package com.inossem.warehousestorage_inossem.manage;

import android.app.Dialog;
import android.content.Context;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.NetworkResponse;
import com.android.volley.NoConnectionError;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import com.inossem.utils.constant.UtilsConstant;
import com.inossem.utils.encryption.URLUtils;
import com.inossem.utils.exception.InossemException;
import com.inossem.utils.log.LogUtils;
import com.inossem.utils.request.VolleyListener;
import com.inossem.utils.request.VolleyUtils;
import com.inossem.warehousestorage_inossem.constant.Constant;
import com.inossem.warehousestorage_inossem.constant.RequestConstant;
import com.inossem.warehousestorage_inossem.dialog.DialogUtils;
import com.inossem.warehousestorage_inossem.listener.RequestListener;
import com.inossem.warehousestorage_inossem.listener.StringRequestListener;
import com.inossem.warehousestorage_inossem.model.StringResponse;
import com.inossem.warehousestorage_inossem.utils.SPUtils;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by leij on 2017/6/5.
 */

public class RequestManage {

    private static final String URL = "url:";

    private static final String RESPONSE_CODE = "responseCode:";

    private static final String RESPONSE_INFO = "responseInfo:";

    private static final String RESPONSE_HEADER = "responseHeader:";

    private static final String RESPONSE = "【response】";

    private static final String HEADER_TOKEN = "X-Auth-Token";

    public static String mapEncodeToParams(Map<String, String> map) {
        String result = "";
        if (map.size() > 0) {
            result += "?";
            for (Map.Entry<String, String> entry : map.entrySet()) {
                if (!(entry.getValue().trim() == null) && !"".equals(entry.getValue().trim())) {
                    result += entry.getKey() + "=" + URLUtils.encode(entry.getValue()) + "&";
                }
            }
            result = result.substring(0, result.length() - 1);
        }
        return result;
    }

//    public static String mapToParams(Map<String, String> map) {
//        String result = "";
//        if (map.size() > 0) {
//            result += "?";
//            for (Map.Entry<String, String> entry : map.entrySet()) {
//                if (!(entry.getValue().trim() == null) && !"".equals(entry.getValue().trim())) {
//                    result += entry.getKey() + "=" + entry.getValue() + "&";
//                }
//            }
//            result = result.substring(0, result.length() - 1);
//        }
//        return result;
//    }

    private static void excuteError(Context context, String url, VolleyError error, RequestListener stringRequestListener) {
        StringResponse stringRequestResponse = new StringResponse();
        String responseCode = UtilsConstant.REQUEST_RESULT_CODE_UNKNOWN;
        String responseInfo = stringRequestResponse.getResponseInfo();
        Map<String, String> responseHeaders = stringRequestResponse.getResponseHearder();
        if (error != null) {
            error.printStackTrace();
            if ((error instanceof AuthFailureError) || (error instanceof ServerError)) {
                // SERVERERROR：服务器的响应的一个错误，最有可能的4xx或5xx HTTP状态代码。
                // AuthFailureError：如果在做一个HTTP的身份验证，可能会发生这个错误。m
                NetworkResponse networkResponse = error.networkResponse;
                if (networkResponse != null) {
                    switch (networkResponse.statusCode) {
                        case 400:
                            responseCode = UtilsConstant.REQUEST_RESULT_CODE_400;
                            break;
                        case 401:
                            responseCode = UtilsConstant.REQUEST_RESULT_CODE_401;
                            break;
                        case 403:
                            responseCode = UtilsConstant.REQUEST_RESULT_CODE_403;
                            break;
                        case 404:
                            responseCode = UtilsConstant.REQUEST_RESULT_CODE_404;
                            break;
                        case 500:
                            responseCode = UtilsConstant.REQUEST_RESULT_CODE_500;
                            break;
                        default:
                            responseCode = UtilsConstant.REQUEST_RESULT_CODE_UNKNOWN;
                            break;
                    }
                    //获得请求体信息
                    try {
                        responseInfo = new String(networkResponse.data, Constant.CHARSET);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    //获得请求头信息
                    responseHeaders = networkResponse.headers;
                } else {
                    responseCode = UtilsConstant.REQUEST_RESULT_CODE_AUTHFAILURE_SERVER_ERROR;
                }
            } else if (error instanceof TimeoutError) {
                responseCode = UtilsConstant.REQUEST_RESULT_CODE_TIME_OUT_ERROR;
            } else if (error instanceof NetworkError) {
                responseCode = UtilsConstant.REQUEST_RESULT_CODE_NETWORK_ERROR;
            } else if (error instanceof NoConnectionError) {
                responseCode = UtilsConstant.REQUEST_RESULT_CODE_NO_CONNECTION_ERROR;
            } else if (error instanceof ParseError) {
                responseCode = UtilsConstant.REQUEST_RESULT_CODE_PARSE_ERROR;
            }
        } else {
            responseCode = UtilsConstant.REQUEST_RESULT_CODE_UNKNOWN;
        }
        stringRequestResponse.setResponseCode(responseCode);
        stringRequestResponse.setResponseInfo(responseInfo);
        stringRequestResponse.setResponseHearder(responseHeaders);
        //请求失败响应日志
        LogUtils.logRequestE(context, RESPONSE + "\n" + URL + url + "\n" + RESPONSE_CODE + stringRequestResponse.getResponseCode() + "\n" + RESPONSE_INFO + stringRequestResponse.getResponseInfo(), null);
        if (stringRequestListener.useDefaultError()) {
            stringRequestListener.onDefaultError(context, stringRequestResponse);
        } else {
            stringRequestListener.onError(context, stringRequestResponse);
        }
    }

    private static void excuteSuccess(Context context, String url, String response, Map<String, String> responseHeaders, RequestListener stringRequestListener) {
        StringResponse stringRequestResponse = new StringResponse();
        stringRequestResponse.setResponseCode(UtilsConstant.REQUEST_RESULT_CODE_200);
        stringRequestResponse.setResponseInfo(response);
        stringRequestResponse.setResponseHearder(responseHeaders);
        //请求成功响应日志
        String responseHeader = "";
        if (responseHeaders != null) {
            Map<String, String> responseHeaderMap = responseHeaders;
            for (String key : responseHeaderMap.keySet()) {
                responseHeader = responseHeader + "【" + key + "】=【" + responseHeaderMap.get(key) + "】   ";
            }
        }
        LogUtils.logRequestI(context, RESPONSE + "\n" + URL + url + "\n" + RESPONSE_CODE + stringRequestResponse.getResponseCode() + "\n" + RESPONSE_HEADER + responseHeader + "\n" + RESPONSE_INFO + stringRequestResponse.getResponseInfo());
//        LogUtils.logRequestI(context, RESPONSE + "\n" + URL + url + "\n" + RESPONSE_CODE + stringRequestResponse.getResponseCode() + "\n" + RESPONSE_INFO + stringRequestResponse.getResponseInfo());
        stringRequestListener.onSuccess(stringRequestResponse);
    }

    private static StringRequest getHttpsString(final Context context, int method, String url, Map<String, String> params, StringRequestListener stringRequestListener) {
        Map<String, String> headers = new HashMap<>();
        return VolleyUtils.requestString(context, method, url, headers, params, true, new VolleyListener<String>() {
            @Override
            public void onSuccess(String response, Map<String, String> responseHeaders) {
                excuteSuccess(context, url, response, responseHeaders, stringRequestListener);
            }

            @Override
            public void onError(VolleyError error) {
                excuteError(context, url, error, stringRequestListener);
            }
        });
    }

    public static JsonObjectRequest getHttpsJsonObject(final Context context, int method, String url, String params, StringRequestListener stringRequestListener) {
        Map<String, String> headers = new HashMap<>();
        headers.put(HEADER_TOKEN, SPUtils.getToken(context));
//        params = params != null ? Base64.encodeToString(params.getBytes(), Base64.DEFAULT) : "";
        return VolleyUtils.requestJson(context, method, url, headers, params, true, new VolleyListener<String>() {
            @Override
            public void onSuccess(String response, Map<String, String> responseHeaders) {
                if (responseHeaders != null && responseHeaders.containsKey(HEADER_TOKEN)) {
                    SPUtils.saveToken(context, responseHeaders.get(HEADER_TOKEN));
                }
                excuteSuccess(context, url, response, responseHeaders, stringRequestListener);
            }

            @Override
            public void onError(VolleyError error) {
                excuteError(context, url, error, stringRequestListener);
            }
        });
    }

    public static JsonObjectRequest getHttpsPost(Context context, String url, String params, StringRequestListener stringRequestListener) {
        return getHttpsJsonObject(context, Request.Method.POST, url, params, stringRequestListener);
    }

    public static JsonObjectRequest getHttpsPut(Context context, String url, String params, StringRequestListener stringRequestListener) {
        return getHttpsJsonObject(context, Request.Method.PUT, url, params, stringRequestListener);
    }

    public static JsonObjectRequest getHttpsGet(Context context, String url, StringRequestListener stringRequestListener) {
        return getHttpsJsonObject(context, Request.Method.GET, url, null, stringRequestListener);
    }

    public static JsonObjectRequest getHttpsDelete(Context context, String url, StringRequestListener stringRequestListener) {
        return getHttpsJsonObject(context, Request.Method.DELETE, url, null, stringRequestListener);
    }

    public static String getHttpsPostWithLoading(Context context, String url, String params, StringRequestListener stringRequestListener) {
        return requestHttpsJsonObjectWithLoading(context, Request.Method.POST, url, params, stringRequestListener);
    }

    public static String getHttpsPutWithLoading(Context context, String url, String params, StringRequestListener stringRequestListener) {
        return requestHttpsJsonObjectWithLoading(context, Request.Method.PUT, url, params, stringRequestListener);
    }

    public static String getHttpsGetWithLoading(Context context, String url, StringRequestListener stringRequestListener) {
        return requestHttpsJsonObjectWithLoading(context, Request.Method.GET, url, null, stringRequestListener);
    }

    public static String getHttpsDeleteWithLoading(Context context, String url, StringRequestListener stringRequestListener) {
        return requestHttpsJsonObjectWithLoading(context, Request.Method.DELETE, url, null, stringRequestListener);
    }

    public static String requestHttpsJsonObjectWithLoading(final Context context, int method, String url, String params, StringRequestListener stringRequestListener) {
        Map<String, String> headers = new HashMap<>();
        headers.put(HEADER_TOKEN, SPUtils.getToken(context));
        Dialog loadingDialog = DialogUtils.getLoadingDialog(context, null);
        JsonObjectRequest request = VolleyUtils.requestJson(context, method, url, headers, params, true, new VolleyListener<String>() {
            @Override
            public void onSuccess(String response, Map<String, String> responseHeaders) {
                loadingDialog.cancel();
                if (responseHeaders != null && responseHeaders.containsKey(HEADER_TOKEN)) {
                    SPUtils.saveToken(context, responseHeaders.get(HEADER_TOKEN));
                }
                excuteSuccess(context, url, response, responseHeaders, stringRequestListener);
            }

            @Override
            public void onError(VolleyError error) {
                loadingDialog.cancel();
                excuteError(context, url, error, stringRequestListener);
            }
        });
        String tag = addRequest(context, request, url);
        loadingDialog.setCancelable(false);
        loadingDialog.show();
        return tag;
    }

    private static String addRequest(Context context, com.android.volley.Request<?> request, String url) {
        String tag = null;
        if (request != null) {
            tag = (String) request.getTag();
            VolleyUtils.addRequest(context, request);
        } else {
            requestException(url);
        }
        return tag;
    }

    protected static void requestException(String url) {
        throw new InossemException("request send fail!, request is null, url:" + url);
    }

    public static String getUrl(Context context, String url) {
        return RequestConstant.HTTP + SPUtils.getDomain(context) + ":" + SPUtils.getPort(context) + RequestConstant.URL_PROJECT + url;
    }
}
